#pragma once

// I don't really feel like having to include winsock2.h here,
// but we have to because of Broady::m_sck of type SOCKET
#include <winsock2.h>
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>

namespace Broady {

class Socket;
typedef boost::shared_ptr<Socket> SocketPtr;

class Socket
{
public:
	static SocketPtr Create( void );

	bool IsValid( void ) const;
	SOCKET Handle( void ) const;
	int LastError( void ) const;

	~Socket( void );
	bool Bind( unsigned long ip, unsigned short port );
	bool SendTo( const void* data, unsigned int& len, unsigned long ip, unsigned short port );
	boost::optional<unsigned int> Available( void );
	bool SetBroadcast( bool broadcast );
	boost::optional<bool> RecvFrom( void* buffer, unsigned int& len, unsigned long* ip, unsigned short* port );
	bool GetLocalAddress( unsigned long* ip, unsigned short* port );

private:
	Socket( void );
	bool _Close( void );
	bool _Obtain( void );
	void _PrintError( const char* const name, int error );
	boost::optional<unsigned int> _sendto( SOCKET s, const void* data, unsigned int len, unsigned long ip, unsigned short port );
	boost::optional< std::pair<unsigned int, bool> > _recvfrom( SOCKET s, void* buffer, unsigned int len, unsigned long* ip, unsigned short* port );

private:
	static bool s_init;
	int m_lastError;
	SOCKET m_handle;
};

} // namespace
